<template>
  <ZContainer v-loading="loading"
              :noPadding="true"
              :noBorder="true"
              :class="[
                'dataset-list',
                {
                  'dataset-list--collapse':currentCollapse
                }
              ]">
    <div class="dataset-list__wrapper flex  h-full w-full relative">
      <div class="dataset-list__wrapper-left overflow-hidden h-full flex flex-col"
           v-if="currentPermission['leftAuth']">
        <div style="padding: 0 16px"
             v-if="currentPermission['keywordAuth']">
          <el-input placeholder="Search"
                    prefix-icon="el-icon-search"
                    clearable
                    v-model="searchForm.name"
                    @input="keyWordsChange">
          </el-input>
        </div>

        <div class="flex-1 flex relative flex-col h-0"
             :style="{
                paddingTop:currentPermission['fastAuth'] ? 0: '16px'
              }">

          <div class="flex-1 flex overflow-auto h-0 flex-col">
            <BSort v-model="searchForm.order"
                   v-if="currentPermission['sortAuth']"
                   @event:change="refreshTable"
                   @event:back-default="backDefaultSort"
                   :collapse.sync="sortCollapse" />

            <BFilter v-model="searchForm.filter"
                     :collapse.sync="filterCollapse"
                     @event:change="refreshTable"
                     v-bind="currentFilterProps"
                     v-if="currentPermission['filterAuth']" />

            <BIntegrationGroup :options="integrations"
                               v-model="searchForm.integration"
                               @event:change="refreshTable"
                               v-if="currentPermission['integrationAuth']" />
          </div>

        </div>
      </div>

      <div class="dataset-list__wrapper-right flex-1 w-0 flex flex-col">

        <div class="dataset-list__wrapper-right-action flex items-center"
             v-if="$slots.toolbar && currentPermission['toolbarAuth']">
          <slot name="toolbar">
          </slot>
        </div>

        <div class="flex-1 flex flex-col relative h-0"
             v-loading="resourceLoading">
          <div class="dataset-list__wrapper-right-list flex-1 overflow-auto relative h-0">
            <RecycleScroller class="h-full"
                             :items="comResources"
                             :buffer="15"
                             :item-size="198"
                             size-field="height"
                             :key-field="this.rowKey"
                             v-if="comResources && comResources.length">
              <template v-slot="{item,active,index}">
                <div :class="['b-card flex flex-col cursor-pointer',
                              [`b-card-${model}`],
                              {
                                'b-card-selection--selected':model==='selection'&&isSelectedRow(item),
                                'b-card-selection--disabled':model==='selection'&&isDisabledRow(item),
                              }
                           ]"
                     :is-active="active"
                     @click.stop="onCommand(model==='selection'?'select':'draw',item,index)">
                  <div class="b-card-top flex flex-col justify-between">
                    <div class="b-card-top__top flex items-center">
                      <div class="b-card-top__top-line"
                           :style="{backgroundColor: useStatusColor(item.status)}"></div>

                      <div class="b-card-top__top__hover overflow-hidden relative flex items-center">
                        <div class="b-card-top__top__hover--status"
                             :style="{color:useStatusColor(item.status)}">{{item.status}}</div>
                      </div>

                      <div class="b-card-top__top-name w-4/6 ">
                        <ZTooltip :line="1"
                                  :content="item.name">
                          <div>
                            <span>{{item.name}}</span>
                          </div>
                        </ZTooltip>
                      </div>

                      <div class="b-card-top__top-menu"
                           v-if="currentPermission['moreMenuAuth']">
                        <BMoreMenu :options="dropdownMenus"
                                   :permission="{
                                    delete:deleteButtonAuth && deleteButtonAuth(item),
                                    edit:editButtonAuth && editButtonAuth(item),
                                  }"
                                   @command="(command) => onCommand(command,item)" />
                      </div>
                    </div>

                    <div class="b-card-top__center flex items-center">
                      <div class="b-card-top__center-desc flex-1 w-0">

                        <ZTooltip :line="1"
                                  placement="right"
                                  :content="item.description">
                          <span>{{item.description}}</span>
                        </ZTooltip>
                      </div>
                    </div>

                    <div class="b-card-top__bottom flex items-center">
                      <BLinkBox prefix-icon="cuifont icon_linked_bots"
                                :total="item.botNum"
                                @click="openLinkedBotModal(item)"
                                :name="$t('custom.component.viewComponent.linkedBots')" />
                      <BLinkBox prefix-icon="cuifont icon_linked_widgets"
                                :total="item.modelNum"
                                @click="openLinkedWidgetModal(item)"
                                name="Linked Widgets" />

                      <ZTag :type="useBusinessType(item.businessType)">
                        {{item.businessTypeName}}
                      </ZTag>

                      <BIntegration class="b-card-top__bottom-integration"
                                    :options="item.integrationList || []"
                                    :prop="{name:'name'}" />
                    </div>
                  </div>

                  <div class="b-card-bottom"
                       v-if="currentPermission['cardFooterAuth']">
                    <BCardInfoItem :title="$t('custom.component.viewComponent.created')"
                                   :date="timeFormat(item.createDate,'HH:mm:ss')"
                                   :name="item.creatorName" />
                    <BCardInfoItem :title="$t('custom.component.viewComponent.update')"
                                   :date="timeFormat(item.updateDate,'HH:mm:ss')"
                                   :name="item.updateByName" />
                    <BCardInfoItem :title="$t('custom.component.viewComponent.lastSynced')"
                                   :date="timeFormat(item.lastSyncDate,'HH:mm:ss') || 'Set Data Source'"
                                   @click.stop.native="datasetSetDataSource(item)"
                                   />
                    <BCardInfoItem :title="$t('custom.component.viewComponent.owner')"
                                   :date="item.ownerName" />
                  </div>
                </div>
              </template>
            </RecycleScroller>

            <slot v-else
                  name="empty"></slot>
          </div>

          <div :class="[
          'dataset-list__wrapper-right-footer flex items-center justify-between',
          {
            'flex-row-reverse':paginationPosition === 'left'
          }
        ]"
               v-if="currentPermission['footerAuth']">

            <slot name="footer-action"
                  v-if="$slots['footer-action'] && currentPermission['footerActionAuth']"></slot>

            <slot name="footer-pagination"
                  v-if="currentPermission['paginationAuth']">
              <el-pagination :current-page="searchForm.pagination.currentPage"
                             :page-sizes="searchForm.pagination.pageSizes"
                             :pagerCount="searchForm.pagination.pageCount"
                             :page-size="searchForm.pagination.pageSize"
                             layout="total, sizes, prev, pager, next, jumper"
                             :total="searchForm.pagination.total"
                             @size-change="sizeChangeResource"
                             @current-change="currentChangeResource">
              </el-pagination>
            </slot>
          </div>
        </div>

      </div>
    </div>
  </ZContainer>
</template>

<script>
import ZContainer from '@/components/storybook/z-container'
import BSort from '@/components/storybook/b-sort/index'
import BFilter from '@/components/storybook/b-filter/index'
import BIntegrationGroup from '@/components/storybook/b-integration-group/index'
import { merge, pick, keys, isFunction, debounce, values, get } from 'lodash'
import permissionProps from '../permission.prop'
import ZTooltip from '@/components/storybook/z-tooltip'
import BLinkBox from '@/components/storybook/b-card/link-box'
import BCardInfoItem from '@/components/storybook/b-card/info-item'
import BIntegration from '@/components/storybook/b-integration/index'
import BMoreMenu from '@/components/storybook/b-card/more-menu'
import TagGroup from '@/components/tag-group'
import bus from '@/components/storybook/utilties/bus'
import useGadget from '@/components/storybook/hooks/useGadget'
import useStatusColor from '@/components/storybook/hooks/useStatusColor'
import useBusinessType from '@/components/storybook/hooks/useBusinessType'
import { timeFormat } from '@/components/storybook/utilties/tools'
import ZTag from '@/components/storybook/z-tag'
import { fetchTag, fetchWorkScheduledUser, fetchIntegration, fetcDatasetList } from '@/api/new'
import { parseSearch } from '@/components/storybook/hooks/useFast'

const EVENTS = {
  useGadget,
  useStatusColor,
  useBusinessType,
  timeFormat
}

export default {
  name: 'DatasetList',
  components: {
    ZContainer,
    BSort,
    BFilter,
    BIntegrationGroup,
    ZTooltip,
    BLinkBox,
    BCardInfoItem,
    BIntegration,
    BMoreMenu,
    TagGroup,
    ZTag
  },
  inject: {
    dataFrom: {
      default: ''
    },
    pageFrom: {
      default: ''
    },
    excludeGadgetType: {
      default: () => []
    },
  },
  props: {
    collapse: Boolean,
    // 0:selection 1:variable
    model: {
      type: String,
      default: 'variable'
    },
    filterProps: {
      type: Object,
      default: () => ({})
    },
    paginationPosition: {
      type: String,
      default: 'left'
    },

    // table query parameter
    searchForm: {
      type: Object,
      default: () => ({})
    },

    // format row
    formatRow: Function,

    // format selection dataset data
    formatSelection: Function,
    // selected dataset
    selectionRows: {
      type: Array,
      default: () => ([])
    },
    disabledRowFormat: Function,
    // key of line dataset data
    rowKey: {
      type: String,
      default: 'id'
    },

    // permissions of the operation button
    editButtonAuth: Function,
    deleteButtonAuth: Function,

    // permissions
    permission: Object,
    ...permissionProps

  },
  data () {
    return {
      // loading status
      resourceLoading: false,
      loading: false,

      // collapse status
      sortCollapse: true,
      filterCollapse: true,

      // filter select
      users: [],
      tags: [],
      statusOptions: [],
      integrations: [],
      businessTypes: [],

      resources: [],
      dropdownMenus: Object.freeze([
        {
          command: 'edit',
          icon: 'cuifont icon_edit',
          name: this.$t('custom.component.viewComponent.edit')

        },
        {
          command: 'delete',
          icon: 'cuifont icon_delete',
          name: this.$t('custom.component.viewComponent.delete')
        }
      ]),
      ...EVENTS
    }
  },
  computed: {
    comResources () {
      return this.pageFrom === 'reportLayout' ? this.resources.filter(v => !this.excludeGadgetType.includes(v.gadgetType)) : this.resources
    },
    currentCollapse: {
      get () {
        return !!this.collapse
      },
      set (collapse) {
        this.$emit('update:collapse', collapse)
      }
    },
    currentPermission () {
      return merge(pick(this.$props, keys(permissionProps)), this.permission)
    },
    currentFilterProps () {
      return merge(this.filterProps, {
        users: this.users,
        tags: this.tags,
        statuss: this.statusOptions,
        businessTypes: this.businessTypes
      })
    }
  },
  watch: {
    filterCollapse (collapse) {
      if (!collapse) {
        this.sortCollapse = true
      }
    },
    sortCollapse (collapse) {
      if (!collapse) {
        this.filterCollapse = true
      }
    }
  },
  beforeCreate () {
    bus.$on('event:deleteList', (item) => {
      this.onSelectResource(item)
    })
  },
  created () {
    this.init()
  },
  beforeDestroy () {
    bus.$off('event:deleteList')
  },
  methods: {
    datasetSetDataSource (item) {
      if (!item.lastSyncDate && this.editButtonAuth(item)) {
        this.$emit('editHandle', item, 'seven')
      }
    },
    async getBusinessTypes () {
      const value = window.SITE_CONFIG['dictList'].find(e => e.dictType === 'datasets_type_list')
      if (value) {
        const list = value.dataList || []
        if (this.$hasPermission('sys:widget:type:mspbots internal') && this.$route.path.includes('CrossTenant')) {
          return list.filter(item => item.dictValue === 'MSPbots Internal')
        }

        return list.filter(item => item.dictValue !== 'MSPbots Internal'
        )
      }
      return []
    },
    backDefaultSort () {
      this.searchForm.order = [{ field: 'update_date', sort: 'DESC' }]
      this.refreshTable()
    },
    keyWordsChange: debounce(function () {
      this.resourceLoading = true
      this.searchForm.pagination.currentPage = 1
      return this.getTableData().then(resources => {
        this.resources = resources.records || []
        this.searchForm.pagination.total = resources.total || 0
      }).finally(() => {
        this.resourceLoading = false
      })
    }, 1000),

    onCommand (command, item, index) {
      if (command === 'select' && !this.isDisabledRow(item)) {
        this.onSelectResource(item, index)
      }
      if (command === 'edit') {
        this.onEditResource(item, index)
      }
      if (command === 'draw') {
        this.onDrawResource(item, index)
      }
      if (command === 'clone') {
        this.onCloneResource(item, index)
      }
      if (command === 'delete') {
        this.onDeleteResource(item, index)
      }
    },
    async openLinkedWidgetModal (data) {
      this.$emit('event:select-widget-number', data)
      bus.$emit('event:select-widget-number', data)
    },

    async openLinkedBotModal (data) {
      this.$emit('event:select-bot-number', data)
      bus.$emit('event:select-bot-number', data)
    },
    isSelectedRow (item) {
      return this.selectionRows.some(record => record[this.rowKey] === item[this.rowKey])
    },
    isDisabledRow (item) {
      return isFunction(this.disabledRowFormat) ? this.disabledRowFormat(item) : false
    },
    onSelectResource (item) {
      const row = isFunction(this.formatSelection) ? this.formatSelection(item) : item
      let index = this.selectionRows.findIndex(record => record[this.rowKey] === row[this.rowKey])

      if (index !== -1) {
        this.selectionRows.splice(index, 1)
        return
      }
      this.selectionRows.unshift(row)

      this.$emit('event:select', row)
      bus.$emit('event:select', row)
    },
    onEditResource (item) {
      this.$emit('event:edit', item)
      bus.$emit('event:edit', item)
    },
    onDrawResource (item) {
      this.$emit('event:draw', item)
      bus.$emit('event:draw', item)
    },

    onCloneResource (item) {
      this.$emit('event:clone', item)
      bus.$emit('event:clone', item)
    },
    onDeleteResource (item) {
      this.$store.commit('SET_CONTENT_IS_NEED_REFRESH_CACHE', true)
      this.$emit('event:delete', item)
      bus.$emit('event:delete', item)
    },


    async sizeChangeResource (size) {
      try {
        this.resourceLoading = true
        this.searchForm.pagination.currentPage = 1
        this.searchForm.pagination.pageSize = size
        const resources = await this.getTableData()
        this.resources = resources.records || []
        this.searchForm.pagination.total = resources.total || 0
      } catch (error) {
      } finally {
        this.resourceLoading = false
      }
    },
    async currentChangeResource (current) {
      try {
        this.resourceLoading = true
        this.searchForm.pagination.currentPage = current
        const resources = await this.getTableData()
        this.resources = resources.records || []
        this.searchForm.pagination.total = resources.total || 0
      } catch (error) {
      } finally {
        this.resourceLoading = false
      }
    },

    async refreshTable (refresh) {
      try {
        this.resourceLoading = true
        this.searchForm.pagination.currentPage = 1
        const resources = await this.getTableData(refresh)
        this.resources = resources.records || []
        this.searchForm.pagination.total = resources.total || 0
      } catch (error) {

      } finally {
        this.resourceLoading = false
      }
    },


    async init () {
      try {
        this.loading = true

        const [
          resources,
          users,
          tags,
          integrations,
          statusOptions,
          businessTypes
        ] = await Promise.all([
          this.getTableData(),
          this.getUsers(),
          this.getTags(),
          this.getIntegrations(),
          this.getStatusOptions(),
          this.getBusinessTypes()
        ])
        this.resources = resources.records || []
        this.searchForm.pagination.total = resources.total || 0
        this.tags = tags
        this.users = users.sort((a, b) => a.username.localeCompare(b.username))
        this.integrations = values(integrations).sort((a, b) => (get(a, 'name') || '').charCodeAt(0) - (get(b, 'name') || '').charCodeAt(0))
        this.statusOptions = statusOptions

        this.businessTypes = businessTypes
      } catch (error) {
      } finally {
        this.loading = false
        this.$store.state.REFRESHCACHE = false
      }
    },

    async getTableData (refresh) {
      const params = {
        ...parseSearch(this.searchForm, 'dataset'),
        queryType: refresh || this.$store.state.REFRESHCACHE ? 'REFRESHCACHE' : null,
      }
      const { data: response } = await fetcDatasetList(params)
      if (response.code !== 0) {
        throw response.msg
      }
      const { records = [], ...rest } = response.data || {}
      if (isFunction(this.formatRow)) {
        return {
          ...rest,
          records: records.map(item => this.formatRow(item))
        }
      }
      return response.data || {}
    },
    async getTags () {
      const params = {}

      const { data: response } = await fetchTag(params)

      if (response.code !== 0) {
        throw response.msg
      }

      return response.data || []
    },
    async getUsers () {
      const params = {
        status: 1,
        excludeRegSource: '3'
      }
      const { data: response } = await fetchWorkScheduledUser(params)
      if (response.code !== 0) {
        throw response.msg
      }

      return response.data || []
    },
    async getIntegrations () {
      const params = {
        tenantCode: this.$store.state.user.tenantCode,
        loadType: 3
      }
      const { data: response } = await fetchIntegration(params)
      if (response.code !== 0) {
        throw response.msg
      }
      return response.data || {}
    },
    async getStatusOptions () {
      let options = []
      if (this.$hasPermission(`sys:widget:status:alpha`)) {
        options.push({ dictLabel: 'Alpha', dictValue: 'Alpha' })
      }
      if (this.$hasPermission(`sys:widget:status:requested`)) {
        options.push({ dictLabel: 'Requested', dictValue: 'Requested' })
      }
      if (this.$hasPermission(`sys:widget:status:in-dev`)) {
        options.push({ dictLabel: 'In-Dev', dictValue: 'In-Dev' })
      }
      if (this.$hasPermission(`sys:widget:status:published`)) {
        options.push({ dictLabel: 'Published', dictValue: 'Published' })
      }
      if (this.$hasPermission(`sys:widget:status:in-qa`)) {
        options.push({ dictLabel: 'In-QA', dictValue: 'In-QA' })
      }
      return options
    }

  }
}
</script>

<style lang="scss" scoped>
@import "@/components/storybook/b-card/b-card.scss";
.dataset-list {
  &__wrapper {
    &-left {
      width: 283px;
      transition: all 200ms;
      transition: all 200ms;
      padding: 16px 0px;
      box-shadow: 1px 0px 0px 0px #f0f0f0;
    }
    &-right {
      transition: all 200ms;
      padding-bottom: 16px;
      &-action {
        padding: 16px 16px 0 16px;
      }
      &-list {
        padding: 16px 16px 0;
      }
      &-footer {
        padding: 16px 16px 0;
        & > .el-pagination {
          margin-top: 0;
          padding: 2px 0px;
        }
      }
    }
  }

  &--collapse {
    .dataset-list__wrapper-left {
      width: 0;
    }
  }
}
</style>
